package com.yangye.piconfig.config;

import com.yangye.pisecurity.config.PermitUrlsConfig;
import com.yangye.pisecurity.endpoint.RestAuthenticationEndpoint;
import com.yangye.pisecurity.filter.JwtTokenFilter;
import com.yangye.pisecurity.handler.AuthenticationAccessDeniedHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * Created by yangye on 2019/7/4
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	public static final String AUTHENTICATION_URL = "/auth/login";

	@Autowired
	@Qualifier("piUserDetailsServiceImpl")
	private UserDetailsService userDetailsService;

	@Autowired
	private RestAuthenticationEndpoint restAuthenticationEndpoint;

	@Autowired
	private AuthenticationAccessDeniedHandler accessDeniedHandler;

	@Autowired
	private PermitUrlsConfig permitUrlsConfig;

	@Autowired
	private void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(userDetailsService).
				passwordEncoder(new BCryptPasswordEncoder());
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.csrf().disable()
			// 登录行为由自己实现
			.formLogin().disable()
			// 因为使用jwt，所以不需要HttpSession
			.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
			.authorizeRequests()
			// OPTIONS请求全部放行
			.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
			// 登出行为由自己实现
			.and()
			.logout().disable()
			.exceptionHandling().authenticationEntryPoint(restAuthenticationEndpoint)
			.and()
			.exceptionHandling().accessDeniedHandler(accessDeniedHandler)
			.and()
			// 添加过滤器
			.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
		this.addPermitUrls(http);
	}

	@Bean
	public JwtTokenFilter authenticationTokenFilterBean() throws Exception {
		return new JwtTokenFilter();
	}

	@Bean
	@Override
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}

	public void addPermitUrls(HttpSecurity http) throws Exception {
		HttpSecurity and = http.authorizeRequests().and();
		for (String permitUrl : permitUrlsConfig.getPermitUrls()) {
			and.authorizeRequests().antMatchers(permitUrl).permitAll();
		}
		// 要写在最后面
		and.authorizeRequests().anyRequest().authenticated();
	}

}
